#ifndef EMITTERMANIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define EMITTERMANIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66

#if defined(_MSC_VER) ||                                            \
    (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
     (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif

#include <string>

namespace YAML {
enum EMITTER_MANIP {
    // general manipulators
    Auto,
    TagByKind,
    Newline,

    // output character set
    EmitNonAscii,
    EscapeNonAscii,
    EscapeAsJson,

    // string manipulators
    // Auto, // duplicate
    SingleQuoted,
    DoubleQuoted,
    Literal,

    // null manipulators
    LowerNull,
    UpperNull,
    CamelNull,
    TildeNull,

    // bool manipulators
    YesNoBool,     // yes, no
    TrueFalseBool, // true, false
    OnOffBool,     // on, off
    UpperCase,     // TRUE, N
    LowerCase,     // f, yes
    CamelCase,     // No, Off
    LongBool,      // yes, On
    ShortBool,     // y, t

    // int manipulators
    Dec,
    Hex,
    Oct,

    // document manipulators
    BeginDoc,
    EndDoc,

    // sequence manipulators
    BeginSeq,
    EndSeq,
    Flow,
    Block,

    // map manipulators
    BeginMap,
    EndMap,
    Key,
    Value,
    // Flow, // duplicate
    // Block, // duplicate
    // Auto, // duplicate
    LongKey
};

struct _Indent {
    _Indent(int value_) : value(value_) {}
    int value;
};

inline _Indent Indent(int value) { return _Indent(value); }

struct _Alias {
    _Alias(const std::string& content_) : content(content_) {}
    std::string content;
};

inline _Alias Alias(const std::string& content) { return _Alias(content); }

struct _Anchor {
    _Anchor(const std::string& content_) : content(content_) {}
    std::string content;
};

inline _Anchor Anchor(const std::string& content) { return _Anchor(content); }

struct _Tag {
    struct Type {
        enum value { Verbatim, PrimaryHandle, NamedHandle };
    };

    explicit _Tag(const std::string& prefix_, const std::string& content_,
                  Type::value type_)
        : prefix(prefix_), content(content_), type(type_) {}
    std::string prefix;
    std::string content;
    Type::value type;
};

inline _Tag VerbatimTag(const std::string& content) {
    return _Tag("", content, _Tag::Type::Verbatim);
}

inline _Tag LocalTag(const std::string& content) {
    return _Tag("", content, _Tag::Type::PrimaryHandle);
}

inline _Tag LocalTag(const std::string& prefix, const std::string content) {
    return _Tag(prefix, content, _Tag::Type::NamedHandle);
}

inline _Tag SecondaryTag(const std::string& content) {
    return _Tag("", content, _Tag::Type::NamedHandle);
}

struct _Comment {
    _Comment(const std::string& content_) : content(content_) {}
    std::string content;
};

inline _Comment Comment(const std::string& content) {
    return _Comment(content);
}

struct _Precision {
    _Precision(int floatPrecision_, int doublePrecision_)
        : floatPrecision(floatPrecision_), doublePrecision(doublePrecision_) {}

    int floatPrecision;
    int doublePrecision;
};

inline _Precision FloatPrecision(int n) { return _Precision(n, -1); }

inline _Precision DoublePrecision(int n) { return _Precision(-1, n); }

inline _Precision Precision(int n) { return _Precision(n, n); }
} // namespace YAML

#endif // EMITTERMANIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
